package com.functest.orm

import org.testng.annotations.DataProvider
import org.testng.annotations.Test
import com.functest.framework.BaseFunctionalTest

/**
 * Created with IntelliJ IDEA.
 * User: KovalevAS
 * Date: 06.09.13
 * Time: 16:50
 * To change this template use File | Settings | File Templates.
 */
class AbstractTableMapperTest extends BaseFunctionalTest {


    static AbstractTableMapper tableMapper
    static Mapper mapper
    static String tableName
    static MapperFields builder
    static Field simpleField
    static Field complexField
    static Field calculatedField
    static String keyField

    
    static class AbstractTableMapperSubclass extends AbstractTableMapper{
        AbstractTableMapperSubclass(Mapper mapper, String table, String keyField = mapper.keyField) {
            super(mapper, table, keyField);
        }

        AbstractTableMapperSubclass(MapperFields builder, String table, String keyField = builder.fields.first().name) {
            super (builder, table, keyField)
        }
    }
    
    static {
        simpleField = new Field(name: 'firstField', from: ['first_field'])
        complexField = new Field(name: 'secondField', from: ['first_field', 'second_field'])
        calculatedField = new Field(name: 'calculatedField', from: [])

        builder = new MapperFields().with {
            field(simpleField)
            field(complexField)
            field(calculatedField)
            delegate as MapperFields
        }

        mapper = new Mapper(builder)
        keyField = mapper.keyField
        tableName = 'table'
        tableMapper = new AbstractTableMapperSubclass(mapper, tableName)
    }


    @DataProvider
    Object[][] constructorData() {
        [
                [
                        new AbstractTableMapperSubclass(mapper, tableName, keyField),
                        keyField,
                        mapper.allFields,
                        'mapper, table, keyField'
                ],
                [
                        new AbstractTableMapperSubclass(mapper, tableName),
                        mapper.keyField,
                        mapper.allFields,
                        'mapper, table'
                ],
                [
                        new AbstractTableMapperSubclass(builder, tableName, keyField),
                        keyField,
                        builder.fields,
                        'builder, table, keyField'

                ],
                [
                        new AbstractTableMapperSubclass(builder, tableName),
                        builder.fields.first().name,
                        builder.fields,
                        'builder, table'
                ]
        ]
    }

    @Test(dataProvider = 'constructorData')
    void constructorTest(AbstractTableMapperSubclass tableMapper, String keyField, List<Field> allFields, String description) {
        asTest {
            asStep(description) {
                com.functest.framework.Assertions.weakAssertSilently('', tableMapper.tableName == tableName)
                com.functest.framework.Assertions.weakAssertSilently('', tableMapper.keyField == keyField)
                com.functest.framework.Assertions.weakAssertSilently('', tableMapper.allFields == allFields)
            }
        }
    }

    @Test()
    void getPrefixTest() {
        assert tableMapper.getPrefix() == tableName + '.'
    }

    @Test()
    void getFqSourceNameTest() {
        asTest {
            asStep('positive test: field in bean matches on single field in table') {
                String fieldName = simpleField.simpleName
                String fqName = tableMapper.getFqSourceName(fieldName)
                com.functest.framework.Assertions.weakAssertSilently('', fqName == 'table.first_field')
            }
            asStep('negative test: field in bean matches not on single field in table') {
                String fieldName = complexField.simpleName
                String fqName = tableMapper.getFqSourceName(fieldName)
                com.functest.framework.Assertions.weakAssertSilently('', fqName == null)
            }
            asStep('negative test: empty string field (not existing field in mapper)') {
                try {
                    String fieldName = ''
                    tableMapper.getFqSourceName(fieldName)
                }
                catch (NoSuchFieldException ignored) {
                    com.functest.framework.Assertions.weakAssertSilently('', true)
                }
                catch (Exception ex) {
                    com.functest.framework.Assertions.weakAssertSilently("Unexpected exception: ${ex.message}", false)
                }
            }
        }
    }

    @Test()
    void getFqSourceNamesTest() {
        asTest {
            Map<String, String> fqNames
            String fieldName = ''

            asStep('simple field') {
                fieldName = simpleField.simpleName
                fqNames = tableMapper.getFqSourceNames(fieldName)
                com.functest.framework.Assertions.weakAssertSilently('sizes does not match!', fqNames.size() == simpleField.from.size())
            }
            asStep('calculated field') {
                fieldName = calculatedField.simpleName
                fqNames = tableMapper.getFqSourceNames(fieldName)
                com.functest.framework.Assertions.weakAssertSilently('return map is not empty', fqNames.isEmpty())
            }
            asStep('complex field') {
                fieldName = complexField.simpleName
                fqNames = tableMapper.getFqSourceNames(fieldName)
                com.functest.framework.Assertions.weakAssertSilently('sizes does not match!', fqNames.size() == complexField.from.size())
            }
            asStep('not existing field') {
                fieldName = 'invalidField'
                try {
                    fqNames = tableMapper.getFqSourceNames(fieldName)
                }
                catch (NoSuchFieldException ignored) {
                    com.functest.framework.Assertions.weakAssertSilently('It is perfectly ok', true)
                }
                catch (Exception e) {
                    com.functest.framework.Assertions.weakAssertSilently("unexpected exception $e", false)
                }
            }
        }
    }
}
